import {
	AxiosPromise,
	AxiosHeaders,
	InternalAxiosRequestConfig,
	Method,
	AxiosInstance,
	RawAxiosRequestHeaders,
} from 'axios'
import { HttpInterceptors, ApiResponse } from './request' // 引入自定义的axios拦截器模块

// 定义一个不确定是什么类型但一定是个数组的类型
type NestedArray = number[] | string[] | object[] | NestedArray[]

/**
 * 定义请求配置类型，用于描述发起HTTP请求所需的各种配置项。
 */
export interface HttpRequestConfig {
	url: string // 请求的URL
	method?: Method | string // 请求方法，如'GET'、'POST'等
	headers?: RawAxiosRequestHeaders | AxiosHeaders // 请求头信息
	params?: object | NestedArray // 请求的查询参数对象或数组
	data?: object | NestedArray // 请求体数据对象或数组
	isToken?: boolean // 是否需要携带token
	duplicateRequestValidation?: boolean // 是否启用重复请求验证，默认应为true
	duplicateRequestValidationTime?: number // 重复请求的时间间隔限制
	showLoading?: boolean // 是否显示加载状态
	showErrorMessage?: boolean // 是否显示错误信息
	errorMessageMode?: 'message' | 'notification' | 'none' // 错误提示方式
	timeout?: number // 请求超时时间
}

/**
 * API响应包装类型 - 返回实际的数据
 */
export type ApiPromise<T = any> = Promise<T>

/**
 * HttpServer类，用于封装axios实例并提供简化版的HTTP请求方法。
 */
export class HttpServer {
	axios: AxiosInstance // 存储axios实例
	private httpInterceptors: HttpInterceptors

	/**
	 * 构造函数，初始化axios实例，并通过拦截器模块获取配置好的axios实例。
	 */
	constructor() {
		this.httpInterceptors = new HttpInterceptors()
		this.axios = this.httpInterceptors.getInterceptors()
	}

	/**
	 * 内部方法，为传入的请求配置添加默认值
	 * @param config 请求的原始配置对象
	 * @returns 带有默认配置的请求配置对象
	 */
	private requestWithDefaults(
		config: HttpRequestConfig
	): InternalAxiosRequestConfig {
		const defaultConfig: Partial<HttpRequestConfig> = {
			isToken: true,
			duplicateRequestValidation: true,
			showLoading: true,
			showErrorMessage: true,
			errorMessageMode: 'message',
		}

		return {
			...defaultConfig,
			...config,
		} as InternalAxiosRequestConfig
	}

	/**
	 * 通用请求方法，处理所有类型的HTTP请求。
	 * @param config 请求配置对象，会应用默认配置
	 * @returns ApiPromise，表示异步请求的Promise
	 */
	request<T = any>(config: HttpRequestConfig): ApiPromise<T> {
		return this.axios.request(this.requestWithDefaults(config)) as Promise<T>
	}

	// 以下为简化版的HTTP方法，直接调用request方法并设定method
	post<T = any>(config: Omit<HttpRequestConfig, 'method'>): ApiPromise<T> {
		return this.request<T>({ ...config, method: 'post' })
	}

	get<T = any>(config: Omit<HttpRequestConfig, 'method'>): ApiPromise<T> {
		return this.request<T>({ ...config, method: 'get' })
	}

	delete<T = any>(config: Omit<HttpRequestConfig, 'method'>): ApiPromise<T> {
		return this.request<T>({ ...config, method: 'delete' })
	}

	put<T = any>(config: Omit<HttpRequestConfig, 'method'>): ApiPromise<T> {
		return this.request<T>({ ...config, method: 'put' })
	}

	patch<T = any>(config: Omit<HttpRequestConfig, 'method'>): ApiPromise<T> {
		return this.request<T>({ ...config, method: 'patch' })
	}

	/**
	 * 上传文件
	 * @param config 请求配置
	 * @returns ApiPromise
	 */
	upload<T = any>(
		config: Omit<HttpRequestConfig, 'method'> & {
			file: File | Blob
			filename?: string
			onProgress?: (progress: number) => void
		}
	): ApiPromise<T> {
		const formData = new FormData()
		formData.append('file', config.file, config.filename)

		if (config.data) {
			Object.entries(config.data as Record<string, any>).forEach(
				([key, value]) => {
					formData.append(key, value)
				}
			)
		}

		return this.request<T>({
			...config,
			method: 'post',
			data: formData,
			headers: {
				'Content-Type': 'multipart/form-data',
				...config.headers,
			},
		})
	}

	/**
	 * 下载文件
	 * @param config 请求配置
	 * @returns Promise<Blob>
	 */
	download(config: Omit<HttpRequestConfig, 'method'>): Promise<Blob> {
		return this.axios
			.request({
				...this.requestWithDefaults(config),
				method: 'get',
				responseType: 'blob',
			})
			.then((response) => response.data)
	}

	/**
	 * 批量请求
	 * @param requests 请求配置数组
	 * @returns Promise<T[]>
	 */
	batch<T = any>(requests: HttpRequestConfig[]): Promise<T[]> {
		const promises = requests.map((config) => this.request<T>(config))
		return Promise.all(promises)
	}

	/**
	 * 取消所有正在进行的请求
	 */
	cancelAll(): void {
		// 这里可以实现取消所有请求的逻辑
		console.warn('Cancel all requests is not implemented yet')
	}

	/**
	 * 更新HTTP配置
	 * @param config 新的配置
	 */
	updateConfig(config: any): void {
		this.httpInterceptors.updateConfig(config)
	}

	/**
	 * 添加成功状态码
	 * @param codes 状态码列表
	 */
	addSuccessCode(...codes: (number | string)[]): void {
		this.httpInterceptors.addSuccessCode(...codes)
	}

	/**
	 * 添加token过期状态码
	 * @param codes 状态码列表
	 */
	addTokenExpiredCode(...codes: (number | string)[]): void {
		this.httpInterceptors.addTokenExpiredCode(...codes)
	}

	/**
	 * 获取当前HTTP配置
	 * @returns 当前配置对象
	 */
	getConfig(): any {
		return this.httpInterceptors.getConfig()
	}
}

// 实例化HttpServer并导出，便于其他模块使用
const http = new HttpServer()
export default http

// 导出类型
export type { ApiResponse, HttpRequestConfig as RequestConfigType }
